#!/usr/bin/env python3
"""
简化版dashboard - 使用服务端渲染，避免复杂JavaScript
"""
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import threading
import subprocess
import socket
import ssl
from urllib.parse import urlparse, parse_qs, unquote
from pathlib import Path
import time
import html

class SimpleDashboardHandler(BaseHTTPRequestHandler):
    def __init__(self, proxy_instance, *args, **kwargs):
        self.proxy = proxy_instance
        super().__init__(*args, **kwargs)

    def do_GET(self):
        parsed_path = urlparse(self.path)
        path = parsed_path.path
        query_params = parse_qs(parsed_path.query)
        
        if path == '/':
            self.serve_main_page(query_params)
        elif path == '/copy':
            self.serve_copy_page(query_params)
        elif path == '/replay':
            self.serve_replay_page(query_params)
        else:
            self.send_error(404)
    
    def do_POST(self):
        parsed_path = urlparse(self.path)
        path = parsed_path.path
        
        content_length = int(self.headers.get('Content-Length', 0))
        post_data = self.rfile.read(content_length).decode('utf-8')
        post_params = parse_qs(post_data)
        
        if path == '/replay_request':
            self.handle_replay_post(post_params)
        else:
            self.send_error(404)

    def serve_main_page(self, query_params):
        """主页面 - 显示请求列表"""
        show_idea_only = query_params.get('idea_only', [''])[0] == '1'
        
        # 获取请求数据
        requests = self.proxy.requests_log[-100:] if self.proxy.requests_log else []
        
        # 过滤IDEA请求
        if show_idea_only:
            requests = [req for req in requests 
                       if req.get('headers', {}).get('User-Agent', '').lower().find('idea') >= 0]
        
        # 统计数据
        total_requests = len(self.proxy.requests_log)
        idea_requests = sum(1 for req in self.proxy.requests_log 
                           if req.get('headers', {}).get('User-Agent', '').lower().find('idea') >= 0)
        
        html_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>IDEA Proxy Monitor</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .header {{ background: #667eea; color: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; }}
        .stats {{ display: flex; gap: 20px; margin-bottom: 20px; }}
        .stat {{ background: white; padding: 15px; border-radius: 8px; text-align: center; }}
        .stat-number {{ font-size: 24px; font-weight: bold; color: #667eea; }}
        .controls {{ background: white; padding: 15px; border-radius: 8px; margin-bottom: 20px; }}
        .btn {{ background: #667eea; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; }}
        .btn:hover {{ background: #5a67d8; }}
        .btn-small {{ padding: 4px 8px; font-size: 12px; margin: 2px; }}
        .btn-copy {{ background: #17a2b8; }}
        .btn-replay {{ background: #ffc107; color: #212529; }}
        .btn-detail {{ background: #28a745; }}
        table {{ width: 100%; background: white; border-collapse: collapse; border-radius: 8px; overflow: hidden; }}
        th, td {{ padding: 12px; text-align: left; border-bottom: 1px solid #eee; }}
        th {{ background: #f8f9fa; font-weight: bold; }}
        .idea-row {{ background: #fff3cd; }}
        .time {{ width: 80px; }}
        .method {{ width: 60px; }}
        .actions {{ width: 180px; }}
        .url {{ max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }}
    </style>
</head>
<body>
    <div class="header">
        <h1>🔍 IDEA Proxy Monitor</h1>
        <p>实时监控 IntelliJ IDEA 网络请求</p>
    </div>
    
    <div class="stats">
        <div class="stat">
            <div class="stat-number">{total_requests}</div>
            <div>总请求数</div>
        </div>
        <div class="stat">
            <div class="stat-number">{idea_requests}</div>
            <div>IDEA请求数</div>
        </div>
        <div class="stat">
            <div class="stat-number">{len(requests)}</div>
            <div>当前显示</div>
        </div>
    </div>
    
    <div class="controls">
        <button class="btn" onclick="location.reload()">🔄 刷新</button>
        {('<button class="btn" onclick="location.href=\'/?\'">' + '显示全部</button>') if show_idea_only else ('<button class="btn" onclick="location.href=\'/?idea_only=1\'">' + '仅显示IDEA</button>')}
    </div>
    
    <table>
        <thead>
            <tr>
                <th class="time">时间</th>
                <th class="method">方法</th>
                <th class="url">URL</th>
                <th>客户端</th>
                <th>User-Agent</th>
                <th class="actions">操作</th>
            </tr>
        </thead>
        <tbody>
"""
        
        if not requests:
            html_content += '<tr><td colspan="6" style="text-align: center; padding: 40px;">暂无请求数据</td></tr>'
        else:
            for i, req in enumerate(reversed(requests[-50:])):  # 最近50个请求
                timestamp = req.get('timestamp', '')
                try:
                    from datetime import datetime
                    time_str = datetime.fromisoformat(timestamp.replace('Z', '+00:00')).strftime('%H:%M:%S')
                except:
                    time_str = timestamp[:8] if len(timestamp) > 8 else timestamp
                
                method_line = req.get('method_line', '')
                method = method_line.split(' ')[0] if method_line else 'Unknown'
                url = method_line.split(' ')[1] if len(method_line.split(' ')) > 1 else 'Unknown'
                
                client = req.get('client_addr', 'Unknown')
                user_agent = req.get('headers', {}).get('User-Agent', 'Unknown')
                
                is_idea = user_agent.lower().find('idea') >= 0
                row_class = 'idea-row' if is_idea else ''
                
                # URL截断显示
                display_url = (url[:60] + '...') if len(url) > 60 else url
                
                # User-Agent截断显示
                display_ua = (user_agent[:40] + '...') if len(user_agent) > 40 else user_agent
                
                html_content += f'''
                <tr class="{row_class}">
                    <td class="time">{html.escape(time_str)}</td>
                    <td class="method">{html.escape(method)}</td>
                    <td class="url" title="{html.escape(url)}">{html.escape(display_url)}</td>
                    <td>{html.escape(client)}</td>
                    <td title="{html.escape(user_agent)}">{html.escape(display_ua)}</td>
                    <td class="actions">
                        <button class="btn btn-small btn-copy" onclick="location.href='/copy?id={i}'">📋 复制</button>
                        <button class="btn btn-small btn-replay" onclick="location.href='/replay?id={i}'">🔄 重放</button>
                    </td>
                </tr>
                '''
        
        html_content += """
        </tbody>
    </table>
    
    <div style="margin-top: 20px; text-align: center; color: #666;">
        <p>💡 点击"复制"获取请求内容，点击"重放"重新发送请求</p>
    </div>
</body>
</html>"""
        
        self.send_response(200)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write(html_content.encode('utf-8'))

    def serve_copy_page(self, query_params):
        """复制页面 - 显示请求的详细内容"""
        try:
            req_id = int(query_params.get('id', ['0'])[0])
            requests = list(reversed(self.proxy.requests_log[-50:]))
            
            if req_id >= len(requests):
                self.send_error(404, "请求不存在")
                return
                
            req = requests[req_id]
            
            # 构建完整请求文本
            newline = "\n"
            request_text = req.get('method_line', '') + newline
            headers = req.get('headers', {})
            for key, value in headers.items():
                request_text += f"{key}: {value}{newline}"
            request_text += newline
            if req.get('body'):
                request_text += req.get('body', '')
            
            html_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>复制请求 - IDEA Proxy Monitor</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .container {{ max-width: 800px; margin: 0 auto; }}
        .header {{ background: #17a2b8; color: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; }}
        .content {{ background: white; padding: 20px; border-radius: 8px; }}
        .btn {{ background: #667eea; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; margin: 5px; }}
        .btn:hover {{ background: #5a67d8; }}
        textarea {{ width: 100%; height: 300px; font-family: monospace; font-size: 12px; }}
        .info {{ background: #d4edda; padding: 15px; border-radius: 4px; margin: 10px 0; }}
    </style>
    <script>
        function copyToClipboard() {{
            const textarea = document.getElementById('requestText');
            textarea.select();
            document.execCommand('copy');
            alert('请求内容已复制到剪贴板！');
        }}
    </script>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>📋 复制请求内容</h1>
            <p>请求详细信息</p>
        </div>
        
        <div class="content">
            <div class="info">
                <strong>时间：</strong>{html.escape(req.get('timestamp', ''))}<br>
                <strong>客户端：</strong>{html.escape(req.get('client_addr', ''))}<br>
                <strong>方法：</strong>{html.escape(req.get('method_line', ''))}
            </div>
            
            <h3>完整请求内容：</h3>
            <textarea id="requestText" readonly>{html.escape(request_text)}</textarea>
            
            <div style="margin-top: 15px;">
                <button class="btn" onclick="copyToClipboard()">📋 复制到剪贴板</button>
                <button class="btn" onclick="history.back()">↩️ 返回</button>
            </div>
        </div>
    </div>
</body>
</html>"""
            
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=utf-8')
            self.end_headers()
            self.wfile.write(html_content.encode('utf-8'))
            
        except Exception as e:
            self.send_error(500, f"处理请求时出错: {str(e)}")

    def serve_replay_page(self, query_params):
        """重放页面 - 显示重放表单"""
        try:
            req_id = int(query_params.get('id', ['0'])[0])
            requests = list(reversed(self.proxy.requests_log[-50:]))
            
            if req_id >= len(requests):
                self.send_error(404, "请求不存在")
                return
                
            req = requests[req_id]
            
            html_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>重放请求 - IDEA Proxy Monitor</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .container {{ max-width: 800px; margin: 0 auto; }}
        .header {{ background: #ffc107; color: #212529; padding: 20px; border-radius: 8px; margin-bottom: 20px; }}
        .content {{ background: white; padding: 20px; border-radius: 8px; }}
        .btn {{ background: #667eea; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; margin: 5px; }}
        .btn:hover {{ background: #5a67d8; }}
        .btn-danger {{ background: #dc3545; }}
        .btn-danger:hover {{ background: #c82333; }}
        .info {{ background: #fff3cd; padding: 15px; border-radius: 4px; margin: 10px 0; }}
        pre {{ background: #f8f9fa; padding: 10px; border-radius: 4px; overflow-x: auto; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🔄 重放请求</h1>
            <p>重新发送HTTP请求</p>
        </div>
        
        <div class="content">
            <div class="info">
                <strong>⚠️ 注意：</strong>重放请求将会向目标服务器发送真实的HTTP请求！
            </div>
            
            <h3>请求详情：</h3>
            <pre>{html.escape(req.get('method_line', ''))}
{html.escape(str(req.get('headers', {})))}</pre>
            
            <form method="post" action="/replay_request">
                <input type="hidden" name="req_id" value="{req_id}">
                <button type="submit" class="btn btn-danger">🚀 确认重放请求</button>
                <button type="button" class="btn" onclick="history.back()">↩️ 取消</button>
            </form>
        </div>
    </div>
</body>
</html>"""
            
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=utf-8')
            self.end_headers()
            self.wfile.write(html_content.encode('utf-8'))
            
        except Exception as e:
            self.send_error(500, f"处理请求时出错: {str(e)}")

    def handle_replay_post(self, post_params):
        """处理重放请求"""
        try:
            req_id = int(post_params.get('req_id', ['0'])[0])
            requests = list(reversed(self.proxy.requests_log[-50:]))
            
            if req_id >= len(requests):
                self.send_error(404, "请求不存在")
                return
                
            req = requests[req_id]
            method_line = req.get('method_line', '')
            headers = req.get('headers', {})
            
            # 执行重放
            result = self.replay_request(method_line, headers)
            
            html_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>重放结果 - IDEA Proxy Monitor</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .container {{ max-width: 800px; margin: 0 auto; }}
        .header {{ background: #28a745; color: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; }}
        .content {{ background: white; padding: 20px; border-radius: 8px; }}
        .btn {{ background: #667eea; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; margin: 5px; }}
        .btn:hover {{ background: #5a67d8; }}
        .result {{ background: #f8f9fa; padding: 15px; border-radius: 4px; margin: 10px 0; max-height: 400px; overflow-y: auto; }}
        .error {{ background: #f8d7da; color: #721c24; }}
        .success {{ background: #d4edda; color: #155724; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>✅ 重放完成</h1>
            <p>请求重放结果</p>
        </div>
        
        <div class="content">
            <h3>原始请求：</h3>
            <div class="result">{html.escape(method_line)}</div>
            
            <h3>重放结果：</h3>
            <div class="result {'success' if result.get('success') else 'error'}">
                <pre>{html.escape(result.get('response', result.get('error', '未知错误')))}</pre>
            </div>
            
            <button class="btn" onclick="history.back()">↩️ 返回</button>
            <button class="btn" onclick="location.href='/'">🏠 首页</button>
        </div>
    </div>
</body>
</html>"""
            
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=utf-8')
            self.end_headers()
            self.wfile.write(html_content.encode('utf-8'))
            
        except Exception as e:
            self.send_error(500, f"重放请求时出错: {str(e)}")

    def replay_request(self, method_line, headers):
        """重放HTTP请求"""
        try:
            parts = method_line.split(' ')
            if len(parts) < 2:
                return {'success': False, 'error': '无效的请求格式'}
            
            method = parts[0]
            url = parts[1]
            parsed_url = urlparse(url)
            
            host = parsed_url.netloc
            if ':' in host:
                host, port = host.split(':')
                port = int(port)
            else:
                port = 443 if parsed_url.scheme == 'https' else 80
            
            # 构建HTTP请求
            crlf = "\r\n"
            request_data = f"{method_line}{crlf}"
            for key, value in headers.items():
                request_data += f"{key}: {value}{crlf}"
            request_data += crlf
            
            # 发送请求
            if parsed_url.scheme == 'https':
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                context = ssl.create_default_context()
                context.check_hostname = False
                context.verify_mode = ssl.CERT_NONE
                ssl_sock = context.wrap_socket(sock, server_hostname=host)
                ssl_sock.settimeout(10)
                ssl_sock.connect((host, port))
                ssl_sock.send(request_data.encode('utf-8'))
                
                response = b''
                while True:
                    try:
                        data = ssl_sock.recv(4096)
                        if not data:
                            break
                        response += data
                        if len(response) > 10240:  # 限制响应大小
                            break
                    except socket.timeout:
                        break
                ssl_sock.close()
            else:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(10)
                sock.connect((host, port))
                sock.send(request_data.encode('utf-8'))
                
                response = b''
                while True:
                    try:
                        data = sock.recv(4096)
                        if not data:
                            break
                        response += data
                        if len(response) > 10240:
                            break
                    except socket.timeout:
                        break
                sock.close()
            
            return {
                'success': True,
                'response': response.decode('utf-8', errors='ignore')[:2000]
            }
            
        except Exception as e:
            return {'success': False, 'error': str(e)}

    def log_message(self, format, *args):
        # 禁用HTTP服务器日志
        pass


class SimpleDashboard:
    def __init__(self, proxy_instance, port=8081):
        self.proxy = proxy_instance
        self.port = port
        self.server = None
        self.thread = None

    def start(self):
        """启动dashboard服务器"""
        def handler(*args, **kwargs):
            return SimpleDashboardHandler(self.proxy, *args, **kwargs)
        
        self.server = HTTPServer(('0.0.0.0', self.port), handler)
        self.thread = threading.Thread(target=self.server.serve_forever)
        self.thread.daemon = True
        self.thread.start()
        
        # 获取WSL IP地址
        try:
            result = subprocess.run(['hostname', '-I'], capture_output=True, text=True, timeout=5)
            wsl_ip = result.stdout.strip().split()[0] if result.stdout.strip() else "localhost"
            print(f"🌐 Simple Dashboard started:")
            print(f"   WSL访问: http://localhost:{self.port}")
            print(f"   Windows访问: http://{wsl_ip}:{self.port}")
        except:
            print(f"🌐 Simple Dashboard started at http://0.0.0.0:{self.port}")

    def stop(self):
        """停止dashboard服务器"""
        if self.server:
            self.server.shutdown()
            self.server.server_close()
        if self.thread:
            self.thread.join()


if __name__ == '__main__':
    # 测试用例
    class MockProxy:
        def __init__(self):
            from datetime import datetime
            self.requests_log = [
                {
                    'timestamp': datetime.now().isoformat(),
                    'client_addr': '127.0.0.1:12345',
                    'method_line': 'GET https://plugins.jetbrains.com/api/plugins HTTP/1.1',
                    'headers': {
                        'User-Agent': 'IntelliJ IDEA/2023.3',
                        'Host': 'plugins.jetbrains.com'
                    }
                }
            ]
    
    mock_proxy = MockProxy()
    dashboard = SimpleDashboard(mock_proxy)
    dashboard.start()
    
    try:
        print("Simple Dashboard running... Press Ctrl+C to stop")
        import time
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        dashboard.stop()
        print("Dashboard stopped")